#include "FluxGraph.h"
#include <sstream>

static bool contain(vector<int> self, int x) {
	for (unsigned i=0; i<self.size(); i++)
		if (x == self.at(i))
			return true;
	return false;
}

void FluxGraph::addEdge(int vertex, int vertex2) {
	_vertex_list[vertex].push_back(vertex2);
}

void FluxGraph::delEdge(int vertex1, int vertex2) {
	vector<int> tmp1 = _vertex_list[vertex1];

	for (unsigned i = 0; i < tmp1.size(); i++) {
		if (tmp1[i] == vertex2) {
			_vertex_list[vertex1].erase(_vertex_list[vertex1].begin() + i);
			break;
		}
	}
}

void
FluxGraph::showTags() {
	for (int i = 0; i < getNbVertex(); ++i) {

		for (int j = 0; j < getNbVertex(); ++j) {
			std::cout << tagged_edges[i][j] << " ";
		}
		cout << endl;
	}
}

void
FluxGraph::invertEdge(int i, int j) {
	delEdge(i, j);
	addEdge(j, i);
}

FluxGraph::FluxGraph(const Graph *in,vector<int> black)
: Graph()
{
	S = addVertex();
	T = addVertex();
	vector<int> n;

	for (int i=0; i<in->getNbVertex(); i++) {
		addVertex();
	}

	for (int i=0; i<in->getNbVertex(); i++) {
		if (contain(black, i)){
			addEdge(S,i+2);
			n = in->getNeighbours(i);
			for (unsigned j=0; j<n.size(); j++) {
				addEdge(i+2,n[j]+2);
			}
		} else {
			addEdge(i+2,T);
		}
	}
	unsigned size = _vertex_list.size();
	tagged_edges = new bool*[size];
	for (unsigned i = 0; i < size; ++i) {
		tagged_edges[i] = new bool[size];
		for (unsigned j = 0; j < size; ++j) {
			tagged_edges[i][j] = false;
		}
	}
}

string FluxGraph::toString() {
	std::ostringstream s;

	s << "S :";
	for (unsigned int j = 0; j < _vertex_list[0].size(); j++) {
		s << " " << _vertex_list[0][j] - 1;
	}
	s << "\n";

	s << "T :";
	for (unsigned int j = 0; j < _vertex_list[1].size(); j++) {
		s << " " << _vertex_list[1][j] - 1;
	}
	s << "\n";


	for (unsigned int i = 2; i < _vertex_list.size(); i++) {
		s << i - 1 << ":";
		for (unsigned int j = 0; j < _vertex_list[i].size(); j++) {
			if (_vertex_list[i][j] == T) {
				s << " T";
			} else {
				s << " " << _vertex_list[i][j] - 1;
			}
		}
		s << "\n";
	}
	return s.str();
}

bool FluxGraph::isTagged(int i, int j) const {
	return tagged_edges[i][j];
}

void FluxGraph::tag(int i, int j) {
	tagged_edges[i][j] = tagged_edges[j][i] = true;
}

void FluxGraph::untag(int i, int j) {
	tagged_edges[i][j] = tagged_edges[j][i] = false;
}
